"""Project endpoints."""

from __future__ import annotations

import csv
import io

from fastapi import APIRouter, Depends, HTTPException, Query, status
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_current_user, get_db
from app.models.user import User
from app.schemas.base import PaginatedResponse
from app.schemas.project import ProjectCreate, ProjectOut, ProjectUpdate
from app.services.project import ProjectService


router = APIRouter()


def get_project_service(session: AsyncSession = Depends(get_db)) -> ProjectService:
    """Dependency to get ProjectService instance.

    Args:
        session: Database session from dependency injection

    Returns:
        ProjectService instance
    """
    return ProjectService(session)


@router.get("", response_model=PaginatedResponse[ProjectOut])
async def list_projects(
    skip: int = Query(0, ge=0),
    limit: int = Query(20, ge=1, le=100),
    search: str | None = Query(None, max_length=100),
    status: str | None = Query(None, pattern="^(active|completed|archived)$"),
    current_user: User = Depends(get_current_user),
    service: ProjectService = Depends(get_project_service),
) -> PaginatedResponse[ProjectOut]:
    """Get all projects for current user with pagination and filters."""
    projects, total = await service.get_projects_with_search(
        skip=skip,
        limit=limit,
        owner_id=current_user.id,
        search=search,
        status=status,
    )
    items = [ProjectOut.model_validate(p) for p in projects]
    return PaginatedResponse(data=items, total=total, skip=skip, limit=limit)


@router.post("", response_model=ProjectOut, status_code=status.HTTP_201_CREATED)
async def create_project(
    project: ProjectCreate,
    current_user: User = Depends(get_current_user),
    service: ProjectService = Depends(get_project_service),
) -> ProjectOut:
    """Create a new project."""
    db_project = await service.create_project(project, owner_id=current_user.id)
    return ProjectOut.model_validate(db_project)


@router.get("/{project_id}", response_model=ProjectOut)
async def get_project(
    project_id: int,
    current_user: User = Depends(get_current_user),
    service: ProjectService = Depends(get_project_service),
) -> ProjectOut:
    """Get a specific project."""
    db_project = await service.get_by_id(project_id)
    if not db_project:
        raise HTTPException(status_code=404, detail="Project not found")
    if db_project.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="Not authorized")
    return ProjectOut.model_validate(db_project)


@router.patch("/{project_id}", response_model=ProjectOut)
async def update_project(
    project_id: int,
    project: ProjectUpdate,
    current_user: User = Depends(get_current_user),
    service: ProjectService = Depends(get_project_service),
) -> ProjectOut:
    """Update a project."""
    db_project = await service.get_by_id(project_id)
    if not db_project:
        raise HTTPException(status_code=404, detail="Project not found")
    if db_project.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="Not authorized")

    updated_project = await service.update_project(project_id, project)
    if not updated_project:
        raise HTTPException(status_code=404, detail="Project not found")
    return ProjectOut.model_validate(updated_project)


@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_project(
    project_id: int,
    current_user: User = Depends(get_current_user),
    service: ProjectService = Depends(get_project_service),
):
    """Delete a project."""
    db_project = await service.get_by_id(project_id)
    if not db_project:
        raise HTTPException(status_code=404, detail="Project not found")
    if db_project.owner_id != current_user.id:
        raise HTTPException(status_code=403, detail="Not authorized")

    await service.delete(project_id)


class BatchDeleteRequest(BaseModel):
    """Request for batch delete."""

    project_ids: list[int]


@router.post("/batch-delete", status_code=status.HTTP_200_OK)
async def batch_delete(
    request: BatchDeleteRequest,
    current_user: User = Depends(get_current_user),
    service: ProjectService = Depends(get_project_service),
) -> dict[str, int]:
    """Batch delete projects."""
    deleted_count = await service.batch_delete_by_owner(request.project_ids, current_user.id)
    return {"deleted": deleted_count}


@router.get("/export/csv")
async def export_csv(
    search: str | None = Query(None, max_length=100),
    status: str | None = Query(None, pattern="^(active|completed|archived)$"),
    current_user: User = Depends(get_current_user),
    service: ProjectService = Depends(get_project_service),
) -> StreamingResponse:
    """Export projects to CSV."""
    projects, _ = await service.get_projects_with_search(
        skip=0,
        limit=10000,
        owner_id=current_user.id,
        search=search,
        status=status,
    )

    output = io.StringIO()
    writer = csv.writer(output)
    writer.writerow(["ID", "Name", "Description", "Status", "Created At", "Updated At"])

    for project in projects:
        writer.writerow(
            [
                project.id,
                project.name,
                project.description or "",
                project.status,
                project.created_at.isoformat(),
                project.updated_at.isoformat(),
            ]
        )

    output.seek(0)
    return StreamingResponse(
        iter([output.getvalue()]), media_type="text/csv", headers={"Content-Disposition": "attachment; filename=projects.csv"}
    )
